package org.piggy.core.netty;

import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;
import org.piggy.common.constants.OtherConst;
import org.piggy.common.utils.RemotingUtil;


/**
 * 连接管理器，管理连接对生命周期
 */
@Slf4j
public class NettyServerManagerHandler extends ChannelDuplexHandler {

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        //当Channel注册到它的EventLoop并且能够处理I/O时调用
        String remoteAddr = RemotingUtil.parseChannelRemoteAddr(ctx.channel());
        log.info("NETTY SERVER PIPELINE: channelRegistered {}", remoteAddr);
        super.channelRegistered(ctx);
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        //当Channel从它的EventLoop中注销并且无法处理任何I/O时调用
        String remoteAddr = RemotingUtil.parseChannelRemoteAddr(ctx.channel());
        log.info("NETTY SERVER PIPELINE: channelUnregistered {}", remoteAddr);
        super.channelUnregistered(ctx);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //当Channel处理于活动状态时被调用，可以接收与发送数据
        String remoteAddr = RemotingUtil.parseChannelRemoteAddr(ctx.channel());
        log.info("NETTY SERVER PIPELINE: channelActive {}", remoteAddr);
        super.channelActive(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        //不再是活动状态且不再连接它的远程节点时被调用
        String remoteAddr = RemotingUtil.parseChannelRemoteAddr(ctx.channel());
        log.info("NETTY SERVER PIPELINE: channelInactive {}", remoteAddr);

        Channel channel1 = ctx.channel();
        Object object = channel1.attr(AttributeKey.valueOf(OtherConst.FUTURE_2)).get();
        if(object != null){
            Channel channel2 = (Channel) object;
            channel2.close();
        }
        channel1.close();
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
        //当 ChannelInboundHandler.fireUserEventTriggered()方法被调用时触发
        if(evt instanceof IdleStateEvent event) {
            if(event.state().equals(IdleState.READER_IDLE)) {
                //有一段时间没有收到或发送任何数据
                String remoteAddr = RemotingUtil.parseChannelRemoteAddr(ctx.channel());
                log.warn("NETTY SERVER PIPELINE: userEventTriggered: IDLE {}", remoteAddr);
                ctx.channel().close();
                log.warn("NETTY SERVER PIPELINE: userEventTriggered: CLOSE {}", ctx.channel().hashCode());
            }
        }
        ctx.fireUserEventTriggered(evt);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //当ChannelHandler在处理过程中出现异常时调用
        String remoteAddr = RemotingUtil.parseChannelRemoteAddr(ctx.channel());
        log.info("NETTY SERVE PIPELINE -> cause ", cause);
        log.info("NETTY SERVER PIPELINE: remoteAddr -> {}",  remoteAddr);
        super.exceptionCaught(ctx, cause);
    }

}
